package com.bsd.xxyp.rdlock.parse;

import cn.hutool.core.collection.ListUtil;
import com.bsd.xxyp.rdlock.annotation.RdLock;
import com.bsd.xxyp.rdlock.context.LockHolder;
import com.bsd.xxyp.rdlock.context.LockAnnotationDataExtractor;
import com.bsd.xxyp.rdlock.exception.RdLockException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.expression.AnnotatedElementKey;
import org.springframework.context.expression.MethodBasedEvaluationContext;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * @author ：wangcheng
 * @date 2022/12/26
 **/
@Slf4j
public class DefaultLockKeyProcessor implements LockKeyProcessor {

    private LockHolder holder;

    public DefaultLockKeyProcessor(LockHolder lockHolder) {
        this.holder = lockHolder;
    }

    public String buildLockKey(LockAnnotationDataExtractor extractor){
        RdLock rdLock = extractor.getRdLock();
        List<String> keyBuilder = new ArrayList<>();
        keyBuilder.add(holder.getLockPrefix());
        if (StringUtils.isBlank(rdLock.bizKey())) {
            keyBuilder = defaultBizKey(extractor);
        }else {
            keyBuilder.add(rdLock.bizKey());
        }
        String elValue = rdLock.value();
        if (StringUtils.isBlank(elValue)) {
            keyBuilder.addAll(parseAnnotationField(extractor));
        }else {
            keyBuilder.addAll(parseEvaluationValue(elValue,extractor));
        }
        return StringUtils.join(keyBuilder,DEFAULT_SEPARATOR);
    }

    protected List<String> parseAnnotationField(LockAnnotationDataExtractor extractor) {
        LockAnnotationFieldParse lockAnnotationFieldParse = holder.getLockAnnotationFieldParse();
        return lockAnnotationFieldParse.parse(extractor);
    }

    protected List<String> parseEvaluationValue(String elValue,LockAnnotationDataExtractor extractor) {
        MethodBasedEvaluationContext methodBasedEvaluationContext = holder.getEvaluationContextProvider().create(extractor);
        LockExpressionEvaluator parseEvaluator = holder.getParseEvaluator();
        AnnotatedElementKey annotatedElementKey = new AnnotatedElementKey(extractor.getTargetMethod(), extractor.getTargetClass());
        List elValueList = parseEvaluator.parseExpression(elValue, annotatedElementKey, methodBasedEvaluationContext, List.class);
        checkParseValue(elValueList,extractor);
        return elValueList;
    }

    private void checkParseValue(List elValueList,LockAnnotationDataExtractor extractor) {
        boolean emptyValueFlag = false;
        if (CollectionUtils.isEmpty(elValueList)) {
            emptyValueFlag = true;
        }else {
            for (Object o : elValueList) {
                if (o == null) {
                    emptyValueFlag = true;
                }else {
                    String var = String.valueOf(o);
                    if (StringUtils.isBlank(var)) {
                        emptyValueFlag = true;
                    }
                }
            }
        }
        if (emptyValueFlag && !extractor.getRdLock().allowValueBlank()) {
            log.error("rdLock el parse fieldValueIsNull in: {} ",extractor.getClassSimpleName()+"#"+extractor.getMethodName());
            throw new RdLockException("rdLock业务key有空值");
        }
    }


    protected List<String> defaultBizKey(LockAnnotationDataExtractor extractor){
        return ListUtil.toList(extractor.getClassSimpleName(), extractor.getMethodName());
    }

}
